{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Day03 `.`、`*`与`+`的用法"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　通过前面两天的内容铺垫，我们已经对什么是**正则表达式**以及什么是**正则表达式**中的**元字符**有了了解，而在**【Day02】**内容中列举的所有**元字符**中，最基础的是`.`、`*`和`+`这3种**元字符**，今天我们就来学习它们的作用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　**【Day02】**中我们介绍了非元字符的其他字符可以用来匹配其自身，但如果我们想要匹配的字符模式中存在不确定的其他字符，譬如对于下面的字符串，如果我们不在乎是什么城市的什么区，只想把具有“XX市XX区”的模式的所有片段都匹配到，就需要使用到`.`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:36.828637Z",
     "iopub.status.busy": "2020-08-26T12:54:36.827639Z",
     "iopub.status.idle": "2020-08-26T12:54:36.839641Z",
     "shell.execute_reply": "2020-08-26T12:54:36.839641Z",
     "shell.execute_reply.started": "2020-08-26T12:54:36.828637Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['重庆市渝北区']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import re\n",
    "\n",
    "s = '重庆市渝北区'\n",
    "\n",
    "re.findall('..市..区', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　这里就利用到了`.`的功能：\n",
    "> 1个`.`代表任意不为换行符的字符出现一次，关于换行符的知识我们之后的日程再介绍，你只需要记住，一个`.`就代表除换行符之外的其他字符，譬如上例中我们用`.`代表1个汉字，两个连续的`.`就代表两个连续汉字，配合固定位置的`市`与`区`，我们就实现了对`XX市XX区`这种模式的匹配"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　但如果我们的字符串中并不是那么完美，像下面的例子一样出现了一些超过两个字的市或区该怎么办呢？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:36.840602Z",
     "iopub.status.busy": "2020-08-26T12:54:36.840602Z",
     "iopub.status.idle": "2020-08-26T12:54:36.844592Z",
     "shell.execute_reply": "2020-08-26T12:54:36.844592Z",
     "shell.execute_reply.started": "2020-08-26T12:54:36.840602Z"
    }
   },
   "outputs": [],
   "source": [
    "s = '成都市天府新区'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　这种时候我们就需要配合`+`来完成任务，它代表着前面最近的模式出现1次或以上："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:36.846587Z",
     "iopub.status.busy": "2020-08-26T12:54:36.846587Z",
     "iopub.status.idle": "2020-08-26T12:54:36.851572Z",
     "shell.execute_reply": "2020-08-26T12:54:36.851572Z",
     "shell.execute_reply.started": "2020-08-26T12:54:36.846587Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['成都市天府新区']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "re.findall('.+市.+区', s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　在这里我们的`.+`就代表任意不为换行符的字符出现至少1次，所以不管是2个字的**成都**还是3个字的**天府新**都能够匹配成功~"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　但是人生就是这样的起起伏伏伏伏伏伏，刚想松口气，结果现在需求变了，不止想要匹配带有`XX市`前缀的结果，如果只有`XX区`，前面没有市的信息也是可以匹配的，那么我们就需要结合`*`来完成新的任务了，它跟`+`很类似，只不过它代表着前面最近的模式出现0次或以上："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:36.853567Z",
     "iopub.status.busy": "2020-08-26T12:54:36.853567Z",
     "iopub.status.idle": "2020-08-26T12:54:36.858555Z",
     "shell.execute_reply": "2020-08-26T12:54:36.858555Z",
     "shell.execute_reply.started": "2020-08-26T12:54:36.853567Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['哈尔滨市道口区']"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s1 = '哈尔滨市道口区'\n",
    "\n",
    "re.findall('.*市*.+区', s1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:36.860548Z",
     "iopub.status.busy": "2020-08-26T12:54:36.860548Z",
     "iopub.status.idle": "2020-08-26T12:54:36.865537Z",
     "shell.execute_reply": "2020-08-26T12:54:36.865537Z",
     "shell.execute_reply.started": "2020-08-26T12:54:36.860548Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['江北区']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s1 = '江北区'\n",
    "\n",
    "re.findall('.*市*.+区', s1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "　　这里的`.*`类似`.+`，但不同的是通过`*`的修饰，我们允许前面最近的模式可以出现0次即不出现也没关系，而`市*`也是一样的道理，这样我们的新正则既对`XX市XX区`的模式进行了匹配，又对`XX区`的模式实现了匹配。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Day03 课后小测验\n",
    "\n",
    "　　相信通过上面的内容，你已经对`.`、`*`和`+`的用法有了一定了解，光说不练假把式，下面请你从给定的字符串中提取出所有完整的英文人名，即你的正则应当匹配到`布莱特·拉特纳`和`克里斯汀·诺兰`，而其它字符串匹配结果应为空列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:54:51.896231Z",
     "iopub.status.busy": "2020-08-26T12:54:51.896231Z",
     "iopub.status.idle": "2020-08-26T12:54:52.460731Z",
     "shell.execute_reply": "2020-08-26T12:54:52.460731Z",
     "shell.execute_reply.started": "2020-08-26T12:54:51.896231Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['布莱特·拉特纳'], ['克里斯汀·诺兰']]\n"
     ]
    }
   ],
   "source": [
    "ss = ['布莱特·拉特纳', '成龙', '克里斯汀·诺兰', '·托马斯']\n",
    "result = []\n",
    "\n",
    "for s in ss:\n",
    "    match_result = re.findall('.+\\·.+', s)\n",
    "    if match_result == []:\n",
    "        pass\n",
    "    else:\n",
    "        # 匹配结果不为空列表则\n",
    "        result.append(match_result)\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2020-08-26T12:55:19.898241Z",
     "iopub.status.busy": "2020-08-26T12:55:19.897245Z",
     "iopub.status.idle": "2020-08-26T12:55:19.904225Z",
     "shell.execute_reply": "2020-08-26T12:55:19.903227Z",
     "shell.execute_reply.started": "2020-08-26T12:55:19.898241Z"
    }
   },
   "source": [
    "　　请将你的答案截图发到本帖评论区~"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
